package com.lanjiyin.cloud.common.util;

import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.security.KeyStore;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import javax.net.ssl.SSLContext;

import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.NameValuePair;
import org.apache.commons.httpclient.cookie.CookiePolicy;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.methods.RequestEntity;
import org.apache.commons.httpclient.methods.StringRequestEntity;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.ssl.SSLContexts;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;

public final class HttpUtils {
	private static Logger logger = LoggerFactory.getLogger(HttpUtils.class);

	private static final MediaType CONTENT_TYPE_FORM = MediaType
			.parse("application/x-www-form-urlencoded;charset=UTF-8");
	private static final MediaType CONTENT_TYPE_JSON = MediaType.parse("application/json; charset=utf-8");
	private static final String DEFAULT_USER_AGENT = "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36";

	private HttpUtils() {
	}

	public static final String httpClientPost(String url) {
		String result = "";
		HttpClient client = new HttpClient();
		GetMethod getMethod = new GetMethod(url);
		client.getParams().setCookiePolicy(CookiePolicy.IGNORE_COOKIES);
		try {
			client.executeMethod(getMethod);
			result = getMethod.getResponseBodyAsString();
		} catch (Exception e) {
			logger.error("", e);
		} finally {
			getMethod.releaseConnection();
		}
		return result;
	}

	public static final String httpClientPost(String url, ArrayList<NameValuePair> list) {
		String result = "";
		HttpClient client = new HttpClient();
		client.getParams().setCookiePolicy(CookiePolicy.IGNORE_COOKIES);
		PostMethod postMethod = new PostMethod(url);
		try {
			NameValuePair[] params = new NameValuePair[list.size()];
			for (int i = 0; i < list.size(); i++) {
				params[i] = list.get(i);
			}
			postMethod.addParameters(params);
			client.executeMethod(postMethod);
			result = postMethod.getResponseBodyAsString();
		} catch (Exception e) {
			logger.error("", e);
		} finally {
			postMethod.releaseConnection();
		}
		return result;
	}

	public static final byte[] httpClientPostByJson(String url, String body) throws Exception {
		final ByteArrayOutputStream data = new ByteArrayOutputStream();
		HttpClient httpClient = new HttpClient();
		httpClient.getParams().setContentCharset("UTF-8");
		PostMethod method = new PostMethod(url);
		RequestEntity entity = new StringRequestEntity(body, "application/json", "UTF-8");
		method.setRequestEntity(entity);
		httpClient.executeMethod(method);
		InputStream in = method.getResponseBodyAsStream();
		final byte[] by = new byte[1024];
		try {
			// 将内容读取内存中
			int len = -1;
			while ((len = in.read(by)) != -1) {
				data.write(by, 0, len);
			}
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			// 关闭流
			in.close();
		}
		return data.toByteArray();
	}

	/**
	 * 
	 * @Title: okHttp3Get @Description: OKHTTP3 GET同步请求 @param @param
	 *         url @param @param params @param @return 参数 @return String
	 *         返回类型 @throws
	 */
	public static String okHttp3Get(String url, Map<String, String> params) {
		StringBuffer sb = new StringBuffer();
		Iterator<Map.Entry<String, String>> itr = params.entrySet().iterator();
		while (itr.hasNext()) {
			Map.Entry<String, String> entry = itr.next();
			sb.append(entry.getKey() + "=" + entry.getValue());
			if (itr.hasNext()) {
				sb.append("&");
			}
		}
		url += "?" + sb.toString();
		Request request = new Request.Builder().url(url).get().build();
		return exec(request);
	}

	/**
	 * GET SSL 同步请求 @Title: okHttp3GetSSL @Description:
	 * TODO(这里用一句话描述这个方法的作用) @param @param url @param @param params @param @return
	 * 参数 @return String 返回类型 @throws
	 */
	public static String okHttp3GetSSL(String url, Map<String, Object> params) {
		StringBuffer sb = new StringBuffer();
		Iterator<Map.Entry<String, Object>> itr = params.entrySet().iterator();
		while (itr.hasNext()) {
			Map.Entry<String, Object> entry = itr.next();
			sb.append(entry.getKey() + "=" + entry.getValue());
			if (itr.hasNext()) {
				sb.append("&");
			}
		}
		url += "?" + sb.toString();
		Request request = new Request.Builder().url(url).get().build();
		return execSSL(request, 20);
	}

	/**
	 * OKHTTP3 POST同步请求
	 */
	public static String post(String url, Map<String, String> params) {
		StringBuffer sb = new StringBuffer();
		Iterator<Map.Entry<String, String>> itr = params.entrySet().iterator();
		while (itr.hasNext()) {
			Map.Entry<String, String> entry = itr.next();
			sb.append(entry.getKey() + "=" + entry.getValue());
			if (itr.hasNext()) {
				sb.append("&");
			}
		}
		RequestBody body = RequestBody.create(CONTENT_TYPE_FORM, sb.toString());
		Request request = new Request.Builder().url(url).post(body).build();
		return exec(request);
	}

	/**
	 * OKHTTP3 POST同步请求
	 */
	public static String postWithHeads(String url, Map<String, String> params, String headerStr) {
		StringBuffer sb = new StringBuffer();
		Iterator<Map.Entry<String, String>> itr = params.entrySet().iterator();
		while (itr.hasNext()) {
			Map.Entry<String, String> entry = itr.next();
			sb.append(entry.getKey() + "=" + entry.getValue());
			if (itr.hasNext()) {
				sb.append("&");
			}
		}
		RequestBody body = RequestBody.create(CONTENT_TYPE_FORM, sb.toString());
		Request request = new Request.Builder().url(url).addHeader("encryptAesKey", headerStr).post(body).build();
		return exec(request);
	}

	/**
	 * OKHTTP3 POST同步请求
	 */
	public static String postHttp(String url, Map<String, Object> params) {
		StringBuffer sb = new StringBuffer();
		Iterator<Map.Entry<String, Object>> itr = params.entrySet().iterator();
		while (itr.hasNext()) {
			Map.Entry<String, Object> entry = itr.next();
			sb.append(entry.getKey() + "=" + entry.getValue());
			if (itr.hasNext()) {
				sb.append("&");
			}
		}
		RequestBody body = RequestBody.create(CONTENT_TYPE_FORM, sb.toString());
		Request request = new Request.Builder().url(url).post(body).build();
		return exec(request);
	}

	/**
	 * OKHTTP3 SSL POST同步请求
	 */
	public static String postOkHttp3SSL(String url, Map<String, Object> params) {
		StringBuffer sb = new StringBuffer();
		Iterator<Map.Entry<String, Object>> itr = params.entrySet().iterator();
		while (itr.hasNext()) {
			Map.Entry<String, Object> entry = itr.next();
			sb.append(entry.getKey() + "=" + entry.getValue().toString());
			if (itr.hasNext()) {
				sb.append("&");
			}
		}
		RequestBody body = RequestBody.create(CONTENT_TYPE_FORM, sb.toString());
		Request request = new Request.Builder().url(url).post(body).build();
		return execSSL(request, 20);
	}

	/**
	 * OKHTTP3 POST同步请求
	 */
	public static String postOkHttp3JSON(String url, String reqBody, int timesout) {
		RequestBody body = RequestBody.create(CONTENT_TYPE_JSON, reqBody);
		Request request = new Request.Builder().url(url).post(body).build();
		return exec1(request, timesout);
	}

	private static String exec1(okhttp3.Request request, int timesout) {
		try {
			OkHttpClient client = new OkHttpClient();
			// 请求超时设置
			client.newBuilder().connectTimeout(10, TimeUnit.SECONDS).readTimeout(timesout, TimeUnit.SECONDS).build();
			okhttp3.Response response = client.newCall(request).execute();
			if (!response.isSuccessful())
				throw new RuntimeException("Unexpected code " + response);
			return response.body().string();
		} catch (IOException e) {
			throw new RuntimeException(e);
		}
	}

	private static String execSSL(okhttp3.Request request, int timesout) {
		try {
			OkHttpClient client = OKHttpClientBuilder.buildOKHttpClient().connectTimeout(10, TimeUnit.SECONDS)
					.readTimeout(timesout, TimeUnit.SECONDS).build();
			okhttp3.Response response = client.newCall(request).execute();
			if (!response.isSuccessful())
				throw new RuntimeException(response.toString());
			return response.body().string();
		} catch (IOException e) {
			logger.error("调用远程API接口异常", e);
			throw new RuntimeException(e);
		}
	}

	private static String exec(okhttp3.Request request) {
		try {
			OkHttpClient client = new OkHttpClient();
			// 请求超时设置
			client.newBuilder().connectTimeout(10, TimeUnit.SECONDS).readTimeout(20, TimeUnit.SECONDS).build();
			okhttp3.Response response = client.newCall(request).execute();
			if (!response.isSuccessful())
				throw new RuntimeException("Unexpected code " + response);
			return response.body().string();
		} catch (IOException e) {
			throw new RuntimeException(e);
		}
	}

	public static String postSSL(String url, String data, String certPath, String certPass) {
		try {
			KeyStore clientStore = KeyStore.getInstance("PKCS12");
			// 读取本机存放的PKCS12证书文件
			FileInputStream instream = new FileInputStream(certPath);
			try {
				// 指定PKCS12的密码(商户ID)
				clientStore.load(instream, certPass.toCharArray());
			} finally {
				instream.close();
			}
			SSLContext sslcontext = SSLContexts.custom().loadKeyMaterial(clientStore, certPass.toCharArray()).build();
			// 指定TLS版本
			SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslcontext, new String[] { "TLSv1" },
					null, SSLConnectionSocketFactory.getDefaultHostnameVerifier());
			// 设置httpclient的SSLSocketFactory
			CloseableHttpClient httpclient = HttpClients.custom().setSSLSocketFactory(sslsf).build();
			try {
				HttpPost httpost = new HttpPost(url); // 设置响应头信息
				httpost.addHeader("Connection", "keep-alive");
				httpost.addHeader("Accept", "*/*");
				httpost.addHeader("Content-Type", CONTENT_TYPE_FORM.toString());
				httpost.addHeader("X-Requested-With", "XMLHttpRequest");
				httpost.addHeader("Cache-Control", "max-age=0");
				httpost.addHeader("User-Agent", DEFAULT_USER_AGENT);
				httpost.setEntity(new StringEntity(data, "UTF-8"));
				CloseableHttpResponse response = httpclient.execute(httpost);
				try {
					HttpEntity entity = response.getEntity();
					String jsonStr = EntityUtils.toString(response.getEntity(), "UTF-8");
					EntityUtils.consume(entity);
					return jsonStr;
				} finally {
					response.close();
				}
			} finally {
				httpclient.close();
			}
		} catch (Exception e) {
			logger.error("", e);
			throw new RuntimeException(e);
		}
	}
}
